// cmd/manage.go
package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"star-go-app/internal/apps/auth/models"
	"star-go-app/internal/apps/auth/models/manager"
	"star-go-app/internal/domain/entities/base_model"
	"star-go-app/pkg/core"
	"star-go-app/pkg/infra/database"
	"strings"
	"time"

	"github.com/spf13/cobra"
	"golang.org/x/text/cases"
	"golang.org/x/text/language"
	"gorm.io/gorm"
)

var (
	configPath string
	db         *gorm.DB
)

func main() {
	var rootCmd = &cobra.Command{
		Use:   "manage",
		Short: "Star Go App 项目管理工具",
		Long:  `Star Go App 项目管理工具，提供数据库迁移、用户管理、Token管理等功能`,
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			// 初始化系统
			if err := initSystem(); err != nil {
				log.Fatalf("系统初始化失败: %v", err)
			}
		},
	}

	// 添加配置文件路径标志
	rootCmd.PersistentFlags().StringVarP(&configPath, "config", "c", "./config.yaml", "配置文件路径")

	// 数据库相关命令
	var dbCmd = &cobra.Command{
		Use:   "db",
		Short: "数据库管理命令",
	}

	var migrateCmd = &cobra.Command{
		Use:   "migrate",
		Short: "执行数据库迁移",
		Run:   runMigration,
	}

	var resetCmd = &cobra.Command{
		Use:   "reset",
		Short: "重置数据库（危险操作）",
		Run:   resetDatabase,
	}

	// Token管理命令
	var tokenCmd = &cobra.Command{
		Use:   "token",
		Short: "Token管理命令",
	}

	var clearExpiredCmd = &cobra.Command{
		Use:   "clear-expired",
		Short: "清除过期的Token",
		Run:   clearExpiredTokens,
	}

	var clearAllCmd = &cobra.Command{
		Use:   "clear-all",
		Short: "清除所有Token（包括黑名单）",
		Run:   clearAllTokens,
	}

	// 用户管理命令
	var userCmd = &cobra.Command{
		Use:   "user",
		Short: "用户管理命令",
	}

	var createSuperuserCmd = &cobra.Command{
		Use:   "create-superuser",
		Short: "创建超级管理员",
		Run:   createSuperuser,
	}

	var changePasswordCmd = &cobra.Command{
		Use:   "change-password",
		Short: "修改用户密码",
		Run:   changePassword,
	}

	var listUsersCmd = &cobra.Command{
		Use:   "list",
		Short: "列出所有用户",
		Run:   listUsers,
	}

	// 应用管理命令（预留功能）
	var appCmd = &cobra.Command{
		Use:   "app",
		Short: "应用管理命令（预留功能）",
	}

	var createAppCmd = &cobra.Command{
		Use:   "create",
		Short: "创建应用（预留功能）",
		Run:   createApp,
	}

	var listAppsCmd = &cobra.Command{
		Use:   "list",
		Short: "列出所有应用（预留功能）",
		Run:   listApps,
	}

	var panelCmd = &cobra.Command{
		Use:   "panel",
		Short: "启动管理面板（预留功能）",
		Run:   startPanel,
	}

	// 构建命令树
	dbCmd.AddCommand(migrateCmd, resetCmd)
	tokenCmd.AddCommand(clearExpiredCmd, clearAllCmd)
	userCmd.AddCommand(createSuperuserCmd, changePasswordCmd, listUsersCmd)
	appCmd.AddCommand(createAppCmd, listAppsCmd, panelCmd)

	rootCmd.AddCommand(dbCmd, tokenCmd, userCmd, appCmd)

	if err := rootCmd.Execute(); err != nil {
		fmt.Fprintf(os.Stderr, "执行命令时出错: %v\n", err)
		os.Exit(1)
	}
}

// 初始化系统
func initSystem() error {
	// 加载配置文件
	if err := core.InitConfig(configPath); err != nil {
		return fmt.Errorf("初始化配置失败: %v", err)
	}

	// 初始化日志系统
	if err := core.InitLogger(); err != nil {
		return fmt.Errorf("初始化日志系统失败: %v", err)
	}

	// 初始化数据库连接
	if err := core.InitDatabase(); err != nil {
		return fmt.Errorf("初始化数据库失败: %v", err)
	}

	db = database.DB
	return nil
}

// 执行数据库迁移
func runMigration(cmd *cobra.Command, args []string) {
	fmt.Println("🚀 开始执行数据库迁移...")

	if err := database.RunMigrations(); err != nil {
		fmt.Printf("❌ 数据库迁移失败: %v\n", err)
		return
	}

	if err := database.InitAdminUser(); err != nil {
		fmt.Printf("❌ 初始化管理员账户失败: %v\n", err)
		return
	}

	fmt.Println("✅ 数据库迁移完成！")
}

// 重置数据库
func resetDatabase(cmd *cobra.Command, args []string) {
	fmt.Print("⚠️  这将删除所有数据，确定要继续吗？ (y/N): ")
	reader := bufio.NewReader(os.Stdin)
	input, _ := reader.ReadString('\n')
	input = strings.TrimSpace(strings.ToLower(input))

	if input != "y" && input != "yes" {
		fmt.Println("操作已取消")
		return
	}

	fmt.Println("🗑️  重置数据库...")

	// 删除所有表
	if err := db.Migrator().DropTable(&models.User{}, &models.Role{}, &models.TokenBlacklist{}, &models.LoginSession{}); err != nil {
		fmt.Printf("❌ 删除表失败: %v\n", err)
		return
	}

	// 重新运行迁移
	runMigration(cmd, args)
}

// 清除过期Token
func clearExpiredTokens(cmd *cobra.Command, args []string) {
	fmt.Println("🧹 清除过期Token...")

	now := time.Now()

	// 清除过期的登录会话
	var expiredSessions int64
	if err := db.Where("expires_at < ?", now).Delete(&models.LoginSession{}).Count(&expiredSessions).Error; err != nil {
		fmt.Printf("❌ 清除过期登录会话失败: %v\n", err)
		return
	}

	// 清除过期的黑名单Token
	var expiredBlacklist int64
	if err := db.Where("expires_at < ?", now).Delete(&models.TokenBlacklist{}).Count(&expiredBlacklist).Error; err != nil {
		fmt.Printf("❌ 清除过期黑名单Token失败: %v\n", err)
		return
	}

	fmt.Printf("✅ 清除完成！登录会话: %d 条，黑名单Token: %d 条\n", expiredSessions, expiredBlacklist)
}

// 清除所有Token
func clearAllTokens(cmd *cobra.Command, args []string) {
	fmt.Print("⚠️  这将清除所有Token和会话，确定要继续吗？ (y/N): ")
	reader := bufio.NewReader(os.Stdin)
	input, _ := reader.ReadString('\n')
	input = strings.TrimSpace(strings.ToLower(input))

	if input != "y" && input != "yes" {
		fmt.Println("操作已取消")
		return
	}

	fmt.Println("🧹 清除所有Token...")

	// 清除所有登录会话
	var allSessions int64
	if err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&models.LoginSession{}).Count(&allSessions).Error; err != nil {
		fmt.Printf("❌ 清除所有登录会话失败: %v\n", err)
		return
	}

	// 清除所有黑名单Token
	var allBlacklist int64
	if err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&models.TokenBlacklist{}).Count(&allBlacklist).Error; err != nil {
		fmt.Printf("❌ 清除所有黑名单Token失败: %v\n", err)
		return
	}

	fmt.Printf("✅ 清除完成！登录会话: %d 条，黑名单Token: %d 条\n", allSessions, allBlacklist)
}

// 创建超级管理员
func createSuperuser(cmd *cobra.Command, args []string) {
	fmt.Println("👨‍💼 创建超级管理员账户")

	reader := bufio.NewReader(os.Stdin)

	fmt.Print("用户名: ")
	username, _ := reader.ReadString('\n')
	username = strings.TrimSpace(username)

	fmt.Print("邮箱: ")
	email, _ := reader.ReadString('\n')
	email = strings.TrimSpace(email)

	fmt.Print("密码: ")
	password, _ := reader.ReadString('\n')
	password = strings.TrimSpace(password)

	// 检查用户名是否已存在
	var existUser models.User
	if err := db.Where("username = ?", username).First(&existUser).Error; err == nil {
		fmt.Printf("❌ 用户名 '%s' 已存在\n", username)
		return
	}

	// 获取管理员角色ID
	var adminRole models.Role
	if err := db.Where("code = ?", models.RoleAdmin).First(&adminRole).Error; err != nil {
		fmt.Printf("❌ 找不到管理员角色: %v\n", err)
		return
	}

	// 创建超级管理员用户
	admin := &models.User{
		Username:    username,
		Email:       email,
		RoleID:      uint(adminRole.ID),
		Status:      base_model.StatusActive,
		IsSuperuser: true,
	}

	// 设置密码
	if err := manager.NewUserDomain().SetPassword(admin, password); err != nil {
		fmt.Printf("❌ 设置密码失败: %v\n", err)
		return
	}

	// 保存到数据库
	if err := db.Create(admin).Error; err != nil {
		fmt.Printf("❌ 创建超级管理员失败: %v\n", err)
		return
	}

	fmt.Printf("✅ 超级管理员 '%s' 创建成功！\n", username)
}

// 修改用户密码
func changePassword(cmd *cobra.Command, args []string) {
	fmt.Println("🔑 修改用户密码")

	reader := bufio.NewReader(os.Stdin)

	fmt.Print("请输入用户名或邮箱: ")
	identifier, _ := reader.ReadString('\n')
	identifier = strings.TrimSpace(identifier)

	fmt.Print("新密码: ")
	newPassword, _ := reader.ReadString('\n')
	newPassword = strings.TrimSpace(newPassword)

	// 查找用户
	var user models.User
	if err := db.Where("username = ? OR email = ?", identifier, identifier).First(&user).Error; err != nil {
		fmt.Printf("❌ 找不到用户: %v\n", err)
		return
	}

	// 修改密码
	if err := manager.NewUserDomain().SetPassword(&user, newPassword); err != nil {
		fmt.Printf("❌ 设置密码失败: %v\n", err)
		return
	}

	// 保存到数据库
	if err := db.Save(&user).Error; err != nil {
		fmt.Printf("❌ 保存用户失败: %v\n", err)
		return
	}

	fmt.Printf("✅ 用户 '%s' 密码修改成功！\n", user.Username)
}

// 列出所有用户
func listUsers(cmd *cobra.Command, args []string) {
	fmt.Println("👥 用户列表")

	var users []models.User
	if err := db.Preload("Role").Find(&users).Error; err != nil {
		fmt.Printf("❌ 查询用户失败: %v\n", err)
		return
	}

	if len(users) == 0 {
		fmt.Println("暂无用户")
		return
	}

	fmt.Printf("%-5s %-20s %-30s %-15s %-12s %-10s\n", "ID", "用户名", "邮箱", "昵称", "角色", "状态")
	fmt.Println(strings.Repeat("-", 95))

	for _, user := range users {
		roleName := "未知"
		if user.Role != nil {
			roleName = user.Role.Name
		}

		status := "正常"
		if user.Status == base_model.StatusInactive {
			status = "禁用"
		}

		fmt.Printf("%-5d %-20s %-30s %-15s %-12s %-10s\n",
			user.ID, user.Username, user.Email, user.Nickname, roleName, status)
	}
}

// 创建应用
func createApp(cmd *cobra.Command, args []string) {
	fmt.Println("📱 创建新应用")

	reader := bufio.NewReader(os.Stdin)

	fmt.Print("请输入应用名称 (英文字符): ")
	appName, _ := reader.ReadString('\n')
	appName = strings.TrimSpace(appName)

	// 验证应用名称
	if appName == "" {
		fmt.Println("❌ 应用名称不能为空")
		return
	}

	// 检查应用名称是否只包含英文字符、数字和下划线
	if !isValidAppName(appName) {
		fmt.Println("❌ 应用名称只能包含英文字符、数字和下划线")
		return
	}

	// 应用目录路径
	appDir := fmt.Sprintf("internal/apps/%s", appName)

	// 检查应用是否已存在
	if _, err := os.Stat(appDir); err == nil {
		fmt.Printf("❌ 应用 '%s' 已存在\n", appName)
		return
	}

	fmt.Printf("🚀 开始创建应用 '%s'...\n", appName)

	// 创建应用目录结构
	if err := createAppStructure(appName, appDir); err != nil {
		fmt.Printf("❌ 创建应用失败: %v\n", err)
		return
	}

	fmt.Printf("✅ 应用 '%s' 创建成功！\n", appName)
	fmt.Println("📁 创建的目录结构:")
	fmt.Printf("   %s/\n", appDir)
	fmt.Println("   ├── controllers/")
	fmt.Println("   ├── models/")
	fmt.Println("   ├── repositories/")
	fmt.Println("   ├── services/")
	fmt.Println("   ├── module.go")
	fmt.Println("   └── routes.go")
	fmt.Println()
	fmt.Println("💡 提示:")
	fmt.Printf("   - 请在 internal/apps/apps.go 中注册新模块 '%s'\n", appName)
	fmt.Println("   - 各层级的使用说明已写入 module.go 文件")
}

// 验证应用名称是否有效
func isValidAppName(name string) bool {
	if len(name) == 0 {
		return false
	}

	for _, char := range name {
		if !((char >= 'a' && char <= 'z') ||
			(char >= 'A' && char <= 'Z') ||
			(char >= '0' && char <= '9') ||
			char == '_') {
			return false
		}
	}
	return true
}

// 创建应用目录结构
func createAppStructure(appName, appDir string) error {
	// 创建主目录
	if err := os.MkdirAll(appDir, 0755); err != nil {
		return fmt.Errorf("创建应用目录失败: %v", err)
	}

	// 创建子目录
	subDirs := []string{"controllers", "models", "repositories", "services"}
	for _, subDir := range subDirs {
		dirPath := fmt.Sprintf("%s/%s", appDir, subDir)
		if err := os.MkdirAll(dirPath, 0755); err != nil {
			return fmt.Errorf("创建子目录 %s 失败: %v", subDir, err)
		}
	}

	// 创建 module.go 文件
	if err := createModuleFile(appName, appDir); err != nil {
		return fmt.Errorf("创建 module.go 失败: %v", err)
	}

	// 创建 routes.go 文件
	if err := createRoutesFile(appName, appDir); err != nil {
		return fmt.Errorf("创建 routes.go 失败: %v", err)
	}

	return nil
}

// 创建 module.go 文件
func createModuleFile(appName, appDir string) error {
	content := fmt.Sprintf(`// internal/apps/%s/module.go
package %s

import (
	"github.com/gin-gonic/gin"
)

/*
快速开发指南：

1. 创建模型 (models/):
   - 在 models/ 目录下创建 xxx.go 文件
   - 定义数据结构体，继承 base_model.BaseModel
   - 添加表名方法: func (X) TableName() string { return "table_name" }

2. 创建数据访问层 (repositories/):
   - 在 repositories/ 目录下创建 xxx_repository.go
   - 定义接口: type XxxRepository interface { Create, Get, Update, Delete... }
   - 实现接口: type xxxRepository struct { db *gorm.DB }

3. 创建业务逻辑层 (services/):
   - 在 services/ 目录下创建 xxx_service.go  
   - 定义服务结构体: type XxxService struct { repo XxxRepository }
   - 实现业务逻辑方法

4. 创建控制器 (controllers/):
   - 在 controllers/ 目录下创建 xxx_controller.go
   - 定义控制器: type XxxController struct { service *XxxService }
   - 实现HTTP处理方法: Create, Get, Update, Delete...

5. 注册路由 (routes.go):
   - 在 registerRoutes 方法中添加路由配置
   - 示例: xxxGroup := router.Group("/xxx")
   - 绑定控制器方法到路由

开发顺序建议: models -> repositories -> services -> controllers -> routes
*/

// Module %s模块
type Module struct{}

// NewModule 创建模块实例
func NewModule() *Module {
	return &Module{}
}

// Name 返回模块名称
func (m *Module) Name() string {
	return "%s"
}

// RegisterRoutes 注册路由
func (m *Module) RegisterRoutes(router *gin.RouterGroup) {
	RegisterRoutes(router)
}

// Initialize 初始化模块
func (m *Module) Initialize() error {
	// 这里可以添加模块初始化逻辑
	// 比如：初始化缓存、验证数据库连接、注册依赖等
	return nil
}
`, appName, appName, appName, appName)

	filePath := fmt.Sprintf("%s/module.go", appDir)
	return os.WriteFile(filePath, []byte(content), 0644)
}

// 创建 routes.go 文件
func createRoutesFile(appName, appDir string) error {
	titleCase := cases.Title(language.English)
	content := fmt.Sprintf(`// internal/apps/%s/routes.go
package %s

import (
	"github.com/gin-gonic/gin"
)

// registerRoutes 注册%s模块的路由
func (m *Module) registerRoutes(router *gin.RouterGroup) {
	// 在这里添加您的路由定义
	// 例如：
	// controller := controllers.New%sController()
	// 
	// %sGroup := router.Group("/%s")
	// {
	//     %sGroup.GET("", controller.List)
	//     %sGroup.POST("", controller.Create)
	//     %sGroup.GET("/:id", controller.GetByID)
	//     %sGroup.PUT("/:id", controller.Update)
	//     %sGroup.DELETE("/:id", controller.Delete)
	// }
}

// RegisterRoutes 公共路由注册函数 (保持向后兼容)
func RegisterRoutes(router *gin.RouterGroup) {
	module := &Module{}
	module.registerRoutes(router)
}
`, appName, appName, appName, titleCase.String(appName), appName, appName, appName, appName, appName, appName, appName)

	filePath := fmt.Sprintf("%s/routes.go", appDir)
	return os.WriteFile(filePath, []byte(content), 0644)
}

// 列出所有应用
func listApps(cmd *cobra.Command, args []string) {
	fmt.Println("📱 应用列表")

	appsDir := "internal/apps"

	// 检查apps目录是否存在
	if _, err := os.Stat(appsDir); os.IsNotExist(err) {
		fmt.Println("❌ apps目录不存在")
		return
	}

	// 读取apps目录
	entries, err := os.ReadDir(appsDir)
	if err != nil {
		fmt.Printf("❌ 读取apps目录失败: %v\n", err)
		return
	}

	// 过滤出应用目录
	var apps []string
	for _, entry := range entries {
		if entry.IsDir() && entry.Name() != "." && entry.Name() != ".." {
			// 检查是否包含module.go文件来确认这是一个应用
			modulePath := fmt.Sprintf("%s/%s/module.go", appsDir, entry.Name())
			if _, err := os.Stat(modulePath); err == nil {
				apps = append(apps, entry.Name())
			}
		}
	}

	if len(apps) == 0 {
		fmt.Println("暂无应用")
		return
	}

	fmt.Printf("找到 %d 个应用:\n\n", len(apps))
	fmt.Printf("%-20s %-30s %-15s\n", "应用名称", "路径", "状态")
	fmt.Println(strings.Repeat("-", 65))

	for _, appName := range apps {
		appPath := fmt.Sprintf("%s/%s", appsDir, appName)
		status := "正常"

		// 检查应用结构完整性
		requiredFiles := []string{"module.go", "routes.go"}
		requiredDirs := []string{"controllers", "models", "repositories", "services"}

		for _, file := range requiredFiles {
			if _, err := os.Stat(fmt.Sprintf("%s/%s", appPath, file)); os.IsNotExist(err) {
				status = "不完整"
				break
			}
		}

		if status == "正常" {
			for _, dir := range requiredDirs {
				if _, err := os.Stat(fmt.Sprintf("%s/%s", appPath, dir)); os.IsNotExist(err) {
					status = "不完整"
					break
				}
			}
		}

		fmt.Printf("%-20s %-30s %-15s\n", appName, appPath, status)
	}

	fmt.Println()
	fmt.Println("💡 提示:")
	fmt.Println("   - '正常' 表示应用结构完整")
	fmt.Println("   - '不完整' 表示缺少必要的文件或目录")
}

// 启动管理面板（预留功能）
func startPanel(cmd *cobra.Command, args []string) {
	fmt.Println("🎛️ 启动管理面板（预留功能）")
	fmt.Println("此功能正在开发中，敬请期待...")

	// TODO: 实现Web管理面板
	// - 用户管理界面
	// - 应用管理界面
	// - 系统监控界面
	// - 日志查看界面

	fmt.Println("计划功能：")
	fmt.Println("- 🌐 Web界面管理用户和角色")
	fmt.Println("- 📊 系统监控和统计面板")
	fmt.Println("- 📝 操作日志查看")
	fmt.Println("- ⚙️ 系统配置管理")
	fmt.Println("- 🔌 API文档和测试工具")
}
